From 6d9725f7fdc97bbb5c04a22fb3f664bda686f048 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 16 Nov 2016 20:51:53 +0100 Subject: [PATCH] snapshot: Add infrastructure to snapshot CSS images Use this infrastructure to render builtin images. Which means from now on, GtkCheckbutton, GtkSpinner and a few others use snapshots. --- gtk/gtkbuiltinicon.c | 21 +++++++++++++ gtk/gtkcssimage.c | 34 +++++++++++++++++++++ gtk/gtkcssimagebuiltin.c | 28 ++++++++++++++++++ gtk/gtkcssimagebuiltinprivate.h | 5 ++++ gtk/gtkcssimageprivate.h | 9 ++++++ gtk/gtkiconhelper.c | 2 +- gtk/gtkrendericon.c | 52 +++++++++++++++++++++++++++++++-- gtk/gtkrendericonprivate.h | 7 ++++- gtk/gtksnapshot.c | 6 ++-- 9 files changed, 156 insertions(+), 8 deletions(-) diff --git a/gtk/gtkbuiltinicon.c b/gtk/gtkbuiltinicon.c index ab294afc22..547fc35a2a 100644 --- a/gtk/gtkbuiltinicon.c +++ b/gtk/gtkbuiltinicon.c @@ -145,6 +145,26 @@ gtk_builtin_icon_draw (GtkCssGadget *gadget, return FALSE; } +static gboolean +gtk_builtin_icon_snapshot (GtkCssGadget *gadget, + GtkSnapshot *snapshot, + int x, + int y, + int width, + int height) +{ + GtkBuiltinIconPrivate *priv = gtk_builtin_icon_get_instance_private (GTK_BUILTIN_ICON (gadget)); + + gtk_snapshot_translate_2d (snapshot, x, y); + gtk_css_style_snapshot_icon (gtk_css_gadget_get_style (gadget), + snapshot, + width, height, + priv->image_type); + gtk_snapshot_translate_2d (snapshot, -x, -y); + + return FALSE; +} + static void gtk_builtin_icon_style_changed (GtkCssGadget *gadget, GtkCssStyleChange *change) @@ -165,6 +185,7 @@ gtk_builtin_icon_class_init (GtkBuiltinIconClass *klass) gadget_class->get_preferred_size = gtk_builtin_icon_get_preferred_size; gadget_class->allocate = gtk_builtin_icon_allocate; gadget_class->draw = gtk_builtin_icon_draw; + gadget_class->snapshot = gtk_builtin_icon_snapshot; gadget_class->style_changed = gtk_builtin_icon_style_changed; } diff --git a/gtk/gtkcssimage.c b/gtk/gtkcssimage.c index 0f6c4e8862..81ab757a14 100644 --- a/gtk/gtkcssimage.c +++ b/gtk/gtkcssimage.c @@ -95,6 +95,21 @@ gtk_css_image_real_transition (GtkCssImage *start, return _gtk_css_image_cross_fade_new (start, end, progress); } +static void +gtk_css_image_real_snapshot (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height) +{ + cairo_t *cr; + + cr = gtk_snapshot_append_cairo_node (snapshot, + &(graphene_rect_t)GRAPHENE_RECT_INIT (0, 0, width, height), + "Fallback<%s>", G_OBJECT_TYPE_NAME (image)); + _gtk_css_image_draw (image, cr, width, height); + cairo_destroy (cr); +} + static void _gtk_css_image_class_init (GtkCssImageClass *klass) { @@ -104,6 +119,7 @@ _gtk_css_image_class_init (GtkCssImageClass *klass) klass->compute = gtk_css_image_real_compute; klass->equal = gtk_css_image_real_equal; klass->transition = gtk_css_image_real_transition; + klass->snapshot = gtk_css_image_real_snapshot; } static void @@ -240,6 +256,24 @@ _gtk_css_image_draw (GtkCssImage *image, cairo_restore (cr); } +void +gtk_css_image_snapshot (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height) +{ + GtkCssImageClass *klass; + + g_return_if_fail (GTK_IS_CSS_IMAGE (image)); + g_return_if_fail (snapshot != NULL); + g_return_if_fail (width > 0); + g_return_if_fail (height > 0); + + klass = GTK_CSS_IMAGE_GET_CLASS (image); + + klass->snapshot (image, snapshot, width, height); +} + void _gtk_css_image_print (GtkCssImage *image, GString *string) diff --git a/gtk/gtkcssimagebuiltin.c b/gtk/gtkcssimagebuiltin.c index 3c045d9a55..841ae91d26 100644 --- a/gtk/gtkcssimagebuiltin.c +++ b/gtk/gtkcssimagebuiltin.c @@ -643,3 +643,31 @@ gtk_css_image_builtin_draw (GtkCssImage *image, } } +void +gtk_css_image_builtin_snapshot (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height, + GtkCssImageBuiltinType image_type) +{ + cairo_t *cr; + + g_return_if_fail (GTK_IS_CSS_IMAGE (image)); + g_return_if_fail (snapshot != NULL); + g_return_if_fail (width > 0); + g_return_if_fail (height > 0); + + if (!GTK_IS_CSS_IMAGE_BUILTIN (image)) + { + gtk_css_image_snapshot (image, snapshot, width, height); + return; + } + + cr = gtk_snapshot_append_cairo_node (snapshot, + &(graphene_rect_t)GRAPHENE_RECT_INIT (0, 0, width, height), + "BuiltinImage<%d>", (int) image_type); + gtk_css_image_builtin_draw (image, cr, width, height, image_type); + cairo_destroy (cr); +} + + diff --git a/gtk/gtkcssimagebuiltinprivate.h b/gtk/gtkcssimagebuiltinprivate.h index 1ceeeff7ef..66c94d2f0a 100644 --- a/gtk/gtkcssimagebuiltinprivate.h +++ b/gtk/gtkcssimagebuiltinprivate.h @@ -57,6 +57,11 @@ void gtk_css_image_builtin_draw (GtkCssImage double width, double height, GtkCssImageBuiltinType image_type); +void gtk_css_image_builtin_snapshot (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height, + GtkCssImageBuiltinType image_type); G_END_DECLS diff --git a/gtk/gtkcssimageprivate.h b/gtk/gtkcssimageprivate.h index 912d0d784b..492734cba2 100644 --- a/gtk/gtkcssimageprivate.h +++ b/gtk/gtkcssimageprivate.h @@ -25,6 +25,7 @@ #include "gtk/gtkcssparserprivate.h" #include "gtk/gtkcsstypesprivate.h" +#include "gtk/gtksnapshotprivate.h" G_BEGIN_DECLS @@ -74,6 +75,10 @@ struct _GtkCssImageClass cairo_t *cr, double width, double height); + void (* snapshot) (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height); /* parse CSS, return TRUE on success */ gboolean (* parse) (GtkCssImage *image, GtkCssParser *parser); @@ -107,6 +112,10 @@ void _gtk_css_image_draw (GtkCssImage * cairo_t *cr, double width, double height); +void gtk_css_image_snapshot (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height); void _gtk_css_image_print (GtkCssImage *image, GString *string); diff --git a/gtk/gtkiconhelper.c b/gtk/gtkiconhelper.c index bd9a6f6bd1..98b0362200 100644 --- a/gtk/gtkiconhelper.c +++ b/gtk/gtkiconhelper.c @@ -870,7 +870,7 @@ gtk_icon_helper_snapshot (GtkIconHelper *self, style = gtk_css_node_get_style (gtk_css_gadget_get_node (GTK_CSS_GADGET (self))); - gtk_css_style_snapshot_icon (style, snapshot, texture); + gtk_css_style_snapshot_icon_texture (style, snapshot, texture); } gboolean diff --git a/gtk/gtkrendericon.c b/gtk/gtkrendericon.c index cd43ec9ecb..8ed65e0d9d 100644 --- a/gtk/gtkrendericon.c +++ b/gtk/gtkrendericon.c @@ -82,6 +82,52 @@ gtk_css_style_render_icon (GtkCssStyle *style, cairo_set_matrix (cr, &saved_matrix); } +void +gtk_css_style_snapshot_icon (GtkCssStyle *style, + GtkSnapshot *snapshot, + double width, + double height, + GtkCssImageBuiltinType builtin_type) +{ + const GtkCssValue *shadows, *transform; + cairo_matrix_t transform_matrix; + graphene_matrix_t matrix, other, saved_matrix; + GtkCssImage *image; + + g_return_if_fail (GTK_IS_CSS_STYLE (style)); + g_return_if_fail (snapshot != NULL); + + image = _gtk_css_image_value_get_image (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SOURCE)); + if (image == NULL) + return; + + shadows = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW); + transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM); + + if (!_gtk_css_transform_value_get_matrix (transform, &transform_matrix)) + return; + + graphene_matrix_init_from_matrix (&saved_matrix, gtk_snapshot_get_transform (snapshot)); + + /* XXX: Implement -gtk-icon-transform-origin instead of hardcoding "50% 50%" here */ + graphene_matrix_init_translate (&matrix, &(graphene_point3d_t)GRAPHENE_POINT3D_INIT(width / 2.0, height / 2.0, 0)); + graphene_matrix_init_from_2d (&other, transform_matrix.xx, transform_matrix.yx, + transform_matrix.xy, transform_matrix.yy, + transform_matrix.x0, transform_matrix.y0); + graphene_matrix_multiply (&other, &matrix, &matrix); + graphene_matrix_init_translate (&other, &(graphene_point3d_t)GRAPHENE_POINT3D_INIT(- width / 2.0, - height / 2.0, 0)); + graphene_matrix_multiply (&matrix, &other, &matrix); + gtk_snapshot_transform (snapshot, &matrix); + + if (!_gtk_css_shadows_value_is_none (shadows)) + { + g_warning ("Painting shadows not implemented for textures yet."); + } + gtk_css_image_builtin_snapshot (image, snapshot, width, height, builtin_type); + + gtk_snapshot_set_transform (snapshot, &saved_matrix); +} + static gboolean get_surface_extents (cairo_surface_t *surface, GdkRectangle *out_extents) @@ -224,9 +270,9 @@ gtk_css_style_render_icon_get_extents (GtkCssStyle *style, } void -gtk_css_style_snapshot_icon (GtkCssStyle *style, - GtkSnapshot *snapshot, - GskTexture *texture) +gtk_css_style_snapshot_icon_texture (GtkCssStyle *style, + GtkSnapshot *snapshot, + GskTexture *texture) { const GtkCssValue *shadows, *transform; cairo_matrix_t transform_matrix; diff --git a/gtk/gtkrendericonprivate.h b/gtk/gtkrendericonprivate.h index 83a3b04cc6..8b12d135bb 100644 --- a/gtk/gtkrendericonprivate.h +++ b/gtk/gtkrendericonprivate.h @@ -37,13 +37,18 @@ void gtk_css_style_render_icon (GtkCssStyle *style, double width, double height, GtkCssImageBuiltinType builtin_type); +void gtk_css_style_snapshot_icon (GtkCssStyle *style, + GtkSnapshot *snapshot, + double width, + double height, + GtkCssImageBuiltinType builtin_type); void gtk_css_style_render_icon_surface (GtkCssStyle *style, cairo_t *cr, cairo_surface_t *surface, double x, double y); -void gtk_css_style_snapshot_icon (GtkCssStyle *style, +void gtk_css_style_snapshot_icon_texture (GtkCssStyle *style, GtkSnapshot *snapshot, GskTexture *texture); diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index 7a7fd6653c..3f2fd4b93b 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -402,9 +402,9 @@ gtk_snapshot_render_icon (GtkSnapshot *snapshot, texture = gsk_texture_new_for_pixbuf (pixbuf); gtk_snapshot_translate_2d (snapshot, x, y); - gtk_css_style_snapshot_icon (gtk_style_context_lookup_style (context), - snapshot, - texture); + gtk_css_style_snapshot_icon_texture (gtk_style_context_lookup_style (context), + snapshot, + texture); gtk_snapshot_translate_2d (snapshot, -x, -y); gsk_texture_unref (texture); } -- 2.30.2